﻿using System;
using Heaven.Graphics;
using XNA = Microsoft.Xna.Framework.Graphics;

namespace Heaven.Xna.Graphics
{
    /// <summary>
    /// Различные состояния устройства рендеринга
    /// </summary>
    internal class RenderStates : IRenderStates
    {
        #region Атрибуты

        // Менеджер рендерстейтов девайса
        XNA.RenderState renderStates;

        // Режим отсечения отвернутых 
        // от камеры полигонов
        CullMode cullMode;
        // Каркасный ли режим?
        bool wireframe;

        // Перезапись свойств, если передаваемое 
        // значение совпадает?
        bool overrideProperties = false;

        #endregion

        #region Инициализация

        /// <summary>
        /// Конструктор
        /// </summary>
        /// <param name="device">Устройство Direct3D</param>
        internal RenderStates(XNA.GraphicsDevice device)
        {
            renderStates = device.RenderState;
            InitStates();
            device.DeviceReset += new EventHandler(OnDeviceReset);
        }

        #endregion

        #region Свойства

        /// <summary>
        /// Вкл/выкл каркасный режим отображения
        /// </summary>
        public bool Wireframe
        {
            get
            {
                return wireframe;
            }
            set
            {
                if (wireframe != value || overrideProperties)
                {
                    if (!value)
                        renderStates.FillMode = XNA.FillMode.Solid;
                    else
                        renderStates.FillMode = XNA.FillMode.WireFrame;

                    wireframe = value;          
                }
            }
        }

        /// <summary>
        /// Режим удаления невидимых граней.
        /// По умолчанию должно быть CounterClockwise.
        /// </summary>
        public CullMode CullMode
        {
            get
            {
                return cullMode;
            }
            set
            {
                if (cullMode != value || overrideProperties)
                {
                    renderStates.CullMode = Converter.Convert(value);
                    cullMode = value;
                }
            }
        }

        #endregion

        #region Методы
	
        /// <summary>
        /// Установка начальных значений
        /// </summary>
        private void InitStates()
        {
            // Инициализируем атрибуты по умолчанию
            cullMode = CullMode.CounterClockwise;
            wireframe = false;

            // Запускаем функцию восстановления, она используя 
            // атрибуты, восстановит значения в девайсе 
            Recover();
        }

        /// <summary>
        /// Восстановление объекта после сброса устройства
        /// </summary>
        public void Recover()
        {
            // Переходим в режим записи в любом случае
            overrideProperties = true;

            // Используя свойства восстанавливаем значения в девайсе
            CullMode = cullMode;
            Wireframe = wireframe;

            // Вновь запрещаем перезапись свойств, 
            // если передаваемое значение совпадает
            overrideProperties = false;
        }

        #endregion

        #region Обработка событий

        void OnDeviceReset(object sender, EventArgs args)
        {
            Recover();
        }

        #endregion
    }
}
